package edu.pku.sei.modeler.uml.commands.sequence;

import edu.pku.sei.modeler.exceptions.FactoryNotFoundException;
import edu.pku.sei.modeler.model.common.ModelRegistry;
import edu.pku.sei.modeler.model.core.MetaModel;
import edu.pku.sei.modeler.model.core.MetaModelElement;
import edu.pku.sei.modeler.model.uml.BasicInteractions.ExecutionSpecification;
import edu.pku.sei.modeler.model.uml.BasicInteractions.Interaction;
import edu.pku.sei.modeler.model.uml.BasicInteractions.Message;
import edu.pku.sei.modeler.model.uml.BasicInteractions.MessageOccurrenceSpecification;
import edu.pku.sei.modeler.uml.commands.ConnectionModelCreateCommand;
import edu.pku.sei.modeler.uml.modelHelper.ModelFactory;
import edu.pku.sei.modeler.model.uml.BasicInteractions.Lifeline;

public class UMLMessageCreateCommand extends ConnectionModelCreateCommand {
	
	public UMLMessageCreateCommand(MetaModelElement connectionModel,
			MetaModelElement sourceModel) {
		super(connectionModel, sourceModel);
	}

	private MessageOccurrenceSpecification startEventOccurrence;
	
	private MessageOccurrenceSpecification finishEventOccurrence;


	@Override
	public boolean canExecute() {
		boolean result = (targetModel instanceof ExecutionSpecification) 
			&& (sourceModel instanceof ExecutionSpecification);
		result = result || ((targetModel instanceof Lifeline) 
		&& (sourceModel instanceof Lifeline));
		return result;
	}

	@Override
	public void execute() {
		
		if (sourceModel instanceof ExecutionSpecification) {
		
			Interaction interaction = (Interaction) sourceModel.getContainer().getContainer();
			Message message = (Message) connectionModel;
			interaction.getMessage().add(message);
			
			MetaModel model = sourceModel.getModel();
	//		message.setModel(model);		
	//		message.getMessageSort().setModel(model);
			
			ExecutionSpecification sourceEO = (ExecutionSpecification) sourceModel;
			ExecutionSpecification targetEO = (ExecutionSpecification) targetModel;
			
			try {
				startEventOccurrence = ((ModelFactory) ModelRegistry
						.getRegistry().getFactory(model)).createMessageOccurrenceSpecification();
				startEventOccurrence.setSendMessage(message);
				startEventOccurrence.setModel(model);
				
				finishEventOccurrence = ((ModelFactory) ModelRegistry
						.getRegistry().getFactory(model)).createMessageOccurrenceSpecification();
				finishEventOccurrence.setReceiveMessage(message);
				finishEventOccurrence.setModel(model);
	//			message.setSendEvent(startEventOccurrence);
	//			message.setReceiveEvent(finishEventOccurrence);
				sourceEO.getStart().add(startEventOccurrence);
				targetEO.getFinish().add(finishEventOccurrence);
				
				
			} catch (IllegalArgumentException e) {
				e.printStackTrace();
			} catch (FactoryNotFoundException e) {
				e.printStackTrace();
			}
		} else if (sourceModel instanceof Lifeline) {
			Interaction interaction = (Interaction) sourceModel.getContainer();
			Message message = (Message) connectionModel;
			interaction.getMessage().add(message);
			
			MetaModel model = sourceModel.getModel();
			
			Lifeline sourceEO = (Lifeline) sourceModel;
			Lifeline targetEO = (Lifeline) targetModel;
			
			try {
				startEventOccurrence = ((ModelFactory) ModelRegistry
						.getRegistry().getFactory(model)).createMessageOccurrenceSpecification();
				startEventOccurrence.setSendMessage(message);
				startEventOccurrence.setModel(model);
				
				finishEventOccurrence = ((ModelFactory) ModelRegistry
						.getRegistry().getFactory(model)).createMessageOccurrenceSpecification();
				finishEventOccurrence.setReceiveMessage(message);
				finishEventOccurrence.setModel(model);
				sourceEO.getStart().add(startEventOccurrence);
				targetEO.getFinish().add(finishEventOccurrence);
				
				
			} catch (IllegalArgumentException e) {
				e.printStackTrace();
			} catch (FactoryNotFoundException e) {
				e.printStackTrace();
			}
		}

	}

	@Override
	public void undo() {
		if (sourceModel instanceof ExecutionSpecification) {
			Interaction interaction = (Interaction)sourceModel.getContainer().getContainer();
			Message message = (Message) connectionModel;
			interaction.getMessage().remove(message);
			ExecutionSpecification sourceEO = (ExecutionSpecification) sourceModel;
			ExecutionSpecification targetEO = (ExecutionSpecification) targetModel;
			sourceEO.getStart().remove(startEventOccurrence);
			targetEO.getFinish().remove(finishEventOccurrence);
		} else if (sourceModel instanceof Lifeline) {
			Interaction interaction = (Interaction)sourceModel.getContainer();
			Message message = (Message) connectionModel;
			interaction.getMessage().remove(message);
			Lifeline sourceEO = (Lifeline) sourceModel;
			Lifeline targetEO = (Lifeline) targetModel;
			sourceEO.getStart().remove(startEventOccurrence);
			targetEO.getFinish().remove(finishEventOccurrence);
		}
	}
}
